package com.bw.coupon.controller;
/**
 * @Author：尚志豪
 * @Package：com.bw.coupon.controller
 * @Project：doudi-group-practical_training-02
 * @name：PaymentController
 * @Date：2025/1/20 15:39
 */

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.easysdk.factory.Factory;
import com.bw.common.core.constant.TokenConstants;
import com.bw.common.core.domain.Result;
import com.bw.common.core.utils.StringUtils;
import com.bw.coupon.annotabon.AliPayConfig;
import com.bw.coupon.annotabon.CheckIdempotent;
import com.bw.coupon.domain.PaymentFlow;
import com.bw.coupon.domain.vo.AliPay;
import com.bw.coupon.service.ICouponService;
import com.bw.coupon.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * @program: doudi-group-practical_training-02
 * @description: 接口幂等处理, 支付宝支付
 * @author: CuiFu Bo
 * @create: 2025-01-20 15:39
 **/
@Component
@RestController
@RequestMapping("alipay")
@Transactional(rollbackFor = Exception.class)
public class PaymentController implements HandlerInterceptor {
    @Autowired
    private ICouponService iCouponService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private HttpServletRequest request;
    @Autowired
    private OrderService orderService;



    /**
     * 获取token
     */
    @GetMapping("/getToken")
    public Result getToken(){
        // 得到token
        String token = UUID.randomUUID().toString();
        redisTemplate.opsForValue().set(token,token,400000L);
        Object o = redisTemplate.opsForValue().get(token);
        if (o !=null){
            return Result.success(token);
        }
        return Result.error("token error");
    }


    /**
     * 用户下单接口
     */
    @GetMapping("/saveOrder")
    @CheckIdempotent
    public Result saveOrder()
    {
        String token = request.getHeader(TokenConstants.TOKEN);
        Boolean delete = redisTemplate.delete(token);
        if (delete)
        {
            System.out.println("*********用户下单成功*********");
            return Result.success("saveOrder success");
        }
        return Result.error("saveOrder error");
    }
    @Resource
    AliPayConfig aliPayConfig;
    // 支付宝沙箱环境网关URL
    private static final String GATEWAY_URL = "https://openapi-sandbox.dl.alipaydev.com/gateway.do";
    // 请求格式为JSON
    private static final String FORMAT = "JSON";
    // 字符集设置为UTF-8
    private static final String CHARSET = "utf-8";
    // 签名方式为RSA2
    private static final String SIGN_TYPE = "RSA2";


    // 支付请求的接口
    // 前端路径参数格式?subject=xxx&traceNo=xxx&totalAmount=xxx
    @GetMapping("/pay")
    // 自定义注解，检查请求幂等性，防止重复支付
    @CheckIdempotent
    public void pay(AliPay aliPay, HttpServletResponse httpResponse) throws Exception {
        // 创建支付宝客户端，使用提供的配置信息
        AlipayClient alipayClient = new DefaultAlipayClient(GATEWAY_URL, aliPayConfig.getAppId(),
                aliPayConfig.getAppPrivateKey(), FORMAT, CHARSET, aliPayConfig.getAlipayPublicKey(), SIGN_TYPE);

        // 创建支付宝请求对象，设置支付相关参数
        AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
        // 设置异步通知URL
        request.setNotifyUrl(aliPayConfig.getNotifyUrl());
        // 设置同步回调URL
        request.setReturnUrl(aliPayConfig.getReturnUrl());

        // 设置支付请求的业务内容
        request.setBizContent("{\"out_trade_no\":\"" + aliPay.getTraceNo() + "\","
                + "\"total_amount\":\"" + aliPay.getTotalAmount() + "\","
                + "\"subject\":\"" + aliPay.getSubject() + "\","
                + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");
        // 用于存储生成的表单HTML
        String form = "";

        try {
            // 调用支付宝SDK生成支付表单
            form = alipayClient.pageExecute(request).getBody();
        } catch (AlipayApiException e) {
            // 处理异常
            e.printStackTrace();
        }

        // 设置响应的内容类型为HTML格式
        httpResponse.setContentType("text/html;charset=" + CHARSET);

        // 将生成的支付表单HTML输出到页面，用户可以直接提交到支付宝
        httpResponse.getWriter().write(form);
        httpResponse.getWriter().flush();
        httpResponse.getWriter().close();
    }

    // 支付宝异步通知接口（用于处理支付结果）
    // 注意这里必须是POST接口
    @PostMapping("/notify")
    // 自定义注解，检查请求幂等性，防止重复支付
    @CheckIdempotent
    public String payNotify(HttpServletRequest request) throws Exception {
        // 检查支付状态是否为成功
        if (request.getParameter("trade_status").equals("TRADE_SUCCESS")) {
            System.out.println("=========支付宝异步回调========");

            // 创建一个Map对象，用于存储通知中传递的参数
            Map<String, String> params = new HashMap<>();
            // 获取请求中的所有参数
            Map<String, String[]> requestParams = request.getParameterMap();
            for (String name : requestParams.keySet()) {
                params.put(name, request.getParameter(name));
            }


            // 验证支付宝通知的签名是否有效
            if (Factory.Payment.Common().verifyNotify(params)) {
                // 验签通过，处理支付成功逻辑
                System.out.println("交易名称: " + params.get("subject"));
                System.out.println("交易状态: " + params.get("trade_status"));
                System.out.println("支付宝交易凭证号: " + params.get("trade_no"));
                System.out.println("商户订单号: " + params.get("out_trade_no"));
                System.out.println("交易金额: " + params.get("total_amount"));
                System.out.println("买家在支付宝唯一id: " + params.get("buyer_id"));
                System.out.println("买家付款时间: " + params.get("gmt_payment"));
                System.out.println("买家付款金额: " + params.get("buyer_pay_amount"));

                //查询订单号是否存在
                PaymentFlow isOutTradeNo = iCouponService.selectOutTradeNo(params.get("out_trade_no"));
                if (!StringUtils.isNull(isOutTradeNo)) {
                    return "";
                }

                // 在此处进行更新订单为已支付的操作
                // 验签通过，处理支付成功逻辑
                PaymentFlow paymentFlow = new PaymentFlow();
                paymentFlow.setOutTradeNo(params.get("out_trade_no"));
                paymentFlow.setTradeNo(params.get("trade_no"));
                paymentFlow.setTotalAmount(params.get("total_amount"));
                paymentFlow.setSubject(params.get("subject"));
                paymentFlow.setTradeStatus(params.get("trade_status"));
                paymentFlow.setGmtPayment(params.get("gmt_payment"));
                paymentFlow.setBuyerId(params.get("buyer_id"));
                paymentFlow.setBuyerPayAmount(params.get("buyer_pay_amount"));

                //添加流水表
               iCouponService.PaymentStatementAdd(paymentFlow);

                //根据订单号查询商品Id
                long outTradeNo = Long.parseLong(params.get("out_trade_no"));
                List<Long> skuIds = orderService.selectOrderNumberBySkuId(outTradeNo);

                //删除购物车
                orderService.deleteCart(skuIds);

                orderService.updateOrderPay(outTradeNo);
            }
        }
        // 返回支付宝确认的成功信息
        return "success";
    }
}
